from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.gis.db import models

import flickrapi
import sys

class LocationType(models.Model):
    name = models.CharField(max_length=200)
    internal_code = models.CharField(max_length=50)
    description = models.TextField(blank=True, null=True)
    
    def __unicode__(self):
        return self.name
    
class Source(models.Model):
    name = models.CharField(max_length=200)
    
    def __unicode__(self):
        return self.name
    
class LocationManager(models.Manager):
    def clustered(self, zoom, swTiles, neTiles, layers):
        from django.db import connection
        cursor = connection.cursor()
        if layers:
            layer_sql = ' AND location_location.type_id in (' + layers + ') '
        else:
            layer_sql = ''
        
        cursor.execute("""
            SELECT count(*) as point_count, 
            min(location_location.id) as id,
            min(location_location.name) as name,
            round(cast (avg(y(coordinates)) as numeric), 5) as latitude,
            round(cast (avg(x(coordinates)) as numeric), 5) as longitude
            FROM location_location JOIN location_locationcluster ON location_location.id = location_locationcluster.location_id 
            WHERE location_locationcluster.zoom = """ + str(zoom) + """
            AND location_locationcluster.tile_x >= """ + str(min(swTiles[0], neTiles[0])) + """
            AND location_locationcluster.tile_x <= """ + str(max(swTiles[0], neTiles[0])) + """
            AND location_locationcluster.tile_y >= """ + str(min(swTiles[1], neTiles[1])) + """
            AND location_locationcluster.tile_y <= """ + str(max(swTiles[1], neTiles[1])) + 
            layer_sql + """
            GROUP BY location_locationcluster.tile_x, location_locationcluster.tile_y""" 
        )
        
        result_list = []
        for row in cursor.fetchall():
            pointCount = row[0]
            if pointCount > 1:
                #clust = Cluster(id=0, point_count=row[0], coordinates="POINT(" + str(row[4]) + " " + str(row[3]) + ")")
                loc = self.model(id=str(row[4]) + "." + str(row[3]), name="cluster", point_count=row[0], coordinates="POINT(" + str(row[4]) + " " + str(row[3]) + ")")
                result_list.append(loc)
            else:
                loc = self.model(id=row[1], name=row[2], point_count=row[0], coordinates="POINT(" + str(row[4]) + " " + str(row[3]) + ")")
                result_list.append(loc)
        return result_list
    
class Location(models.Model):
    xid = models.CharField("External Id", max_length=200, blank=True, null=True)
    name = models.CharField(max_length=200)
    type = models.ForeignKey(LocationType, blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    coordinates = models.PointField()
    company = models.CharField(max_length=400, blank=True, null=True)
    point_count = models.IntegerField(blank=True, null=True)
    source = models.ForeignKey(Source, blank=True, null=True)
    photos_count = models.IntegerField(default=0)
    comments_count = models.IntegerField(default=0)
    
    objects = models.GeoManager()
    locations = LocationManager()
    
    def __unicode__(self):
        return self.name
    
    def get_photos(self):
        # This method skips the Photo related model and goes straight to a Flickr search for improved performance.
        photos = []
        flickr = flickrapi.FlickrAPI(settings.FLICKR_API_KEY, format='etree')
        tag = settings.FLICKR_TAGS_PREFIX + str(self.id)
        photo_result = flickr.photos_search(user_id=settings.FLICKR_USER_ID, tags=tag)
        for photo in photo_result.find('photos').findall('photo'):
            photodict = {'id': photo.attrib['id'], 
                    'server': photo.attrib['server'], 
                    'farm': photo.attrib['farm'],
                    'title': photo.attrib['title'],
                    'secret': photo.attrib['secret']
            }
            photos.append(photodict)
        return photos
        
    
    class Meta:
        ordering = ['name']
            
class LocationCluster(models.Model):
    location = models.ForeignKey(Location)
    zoom = models.IntegerField()
    tile_x = models.IntegerField()
    tile_y = models.IntegerField()

    objects = models.GeoManager()
    
    def __unicode__(self):
        return self.location.name + ' (' + str(self.zoom) + '): ' + str(self.tile_x) + ', ' + str(self.tile_y)
    
    class Meta:
        unique_together = (("location", "zoom"),)
        
class Mine(Location):
    commodity = models.CharField(max_length=400, blank=True, null=True)
    plant_min = models.CharField(max_length=200, blank=True, null=True)
    county = models.CharField(max_length=200, blank=True, null=True)

    objects = models.GeoManager()

    def __unicode__(self):
        commodity_label = self.commodity or 'NONE'
        return self.name + ": " + commodity_label
    
#    def save(self):
#        type = "Mine"
#        super(Mine, self).save()
    
class Quarry(Location):
    commodity = models.CharField(max_length=400, blank=True, null=True)
    plant_min = models.CharField(max_length=200, blank=True, null=True)
    county = models.CharField(max_length=200, blank=True, null=True)

    objects = models.GeoManager()

    def __unicode__(self):
        commodity_label = self.commodity or 'NONE'
        return self.name + ": " + commodity_label
    
    class Meta:
        verbose_name_plural = "quarries"

class LocationComment(models.Model):
    location = models.ForeignKey(Location)
    user = models.ForeignKey(User)
    referenced_comment = models.ForeignKey('self', blank=True, null=True)
    comment = models.TextField()
    posted = models.DateTimeField(auto_now_add=True)
    
    def __unicode__(self):
        return self.comment
    
    class Meta:
        ordering = ['-posted']
    
class Photo(models.Model):
    location = models.ForeignKey(Location)
    file = models.ImageField(upload_to='photos/')
    caption = models.CharField(max_length=400)
    
    def __unicode__(self):
        return self.caption
    
    def save(self):
        # We have to check the ID before calling the super.save()
        if not self.id:
            upload_to_flickr = True
        else:
            upload_to_flickr = False
            
        if upload_to_flickr:
            # Assume insert
            flickr = flickrapi.FlickrAPI(settings.FLICKR_API_KEY, settings.FLICKR_API_SECRET, token=settings.FLICKR_AUTH_TOKEN)
            flickr.upload(filename=self.get_file_filename().encode('ascii','ignore'),
                    title=self.location.name + ': ' + self.caption,
                    tags=settings.FLICKR_TAGS_PREFIX + str(self.location.id),
                    is_public=True
            )
        super(Photo, self).save()        
